package 抽象语法树遍历器;

import 抽象语法树类.*;
import 抽象语法树类.字面量类.*;
import 抽象语法树类.表达式类.*;
import 抽象语法树类.表达式类.二元表达式类.*;
import 抽象语法树类.语句类.*;

public class 抽象语法树遍历器 {

    // 注意：其他所有遍历如果有子节点都得先从遍历抽象语法树开始。因此为了方便，最好除了抽象语法树这个命名为“遍历”，其他的都是“遍历XXXX”。
    
    public void 遍历(抽象语法树监听器 监听器, 抽象语法树 树) {
        if (树 == null) return;
        监听器.进入抽象语法树(树);

        if (树 instanceof 代码块 代码块) {
            遍历代码块(监听器, 代码块);
        } else if (树 instanceof 函数定义 函数定义) {
            遍历函数定义(监听器, 函数定义);
        } else if (树 instanceof 变量定义 变量定义) {
            遍历变量定义(监听器, 变量定义);
        } else if (树 instanceof 程序节点 程序节点) {
            遍历程序节点(监听器, 程序节点);
        } else if (树 instanceof 符号引用 符号引用) {
            遍历符号引用(监听器, 符号引用);
        } else if (树 instanceof 结构体定义 结构体定义) {
            遍历结构体定义(监听器, 结构体定义);
        }

        // 语句类
        else if (树 instanceof 语句 语句) {
            遍历语句(监听器, 语句);
        }

        // 表达式类
        else if (树 instanceof 表达式 表达式) {
            遍历表达式(监听器, 表达式);
        }

        // 字面量
        else if (树 instanceof 字面量 字面量) {
            遍历字面量(监听器, 字面量);
        }

        监听器.离开抽象语法树(树);
    }


    private void 遍历代码块(抽象语法树监听器 监听器, 代码块 代码块) {
        监听器.进入代码块(代码块);
        for (var 语句 : 代码块.语句列表) {
            遍历(监听器, 语句);
        }
        监听器.离开代码块(代码块);
    }

    private void 遍历函数定义(抽象语法树监听器 监听器, 函数定义 函数定义) {
        监听器.进入函数定义(函数定义);

        for (var 参数 : 函数定义.参数) {
            遍历(监听器, 参数);
        }

        遍历(监听器, 函数定义.代码块);

        监听器.离开函数定义(函数定义);
    }

    private void 遍历变量定义(抽象语法树监听器 监听器, 变量定义 变量定义) {
        监听器.进入变量定义(变量定义);
        监听器.离开变量定义(变量定义);
    }

    private void 遍历程序节点(抽象语法树监听器 监听器, 程序节点 程序节点) {
        监听器.进入程序节点(程序节点);

        for (var 子节点 : 程序节点.子节点) {
            遍历(监听器, 子节点);
        }

        监听器.离开程序节点(程序节点);
    }

    private void 遍历符号引用(抽象语法树监听器 监听器, 符号引用 符号引用) {
        监听器.进入符号引用(符号引用);
        监听器.离开符号引用(符号引用);
    }

    private void 遍历结构体定义(抽象语法树监听器 监听器, 结构体定义 结构体定义) {
        监听器.进入结构体定义(结构体定义);

        for (var 成员 : 结构体定义.成员) {
            遍历(监听器, 成员);
        }

        监听器.离开结构体定义(结构体定义);
    }


    // region 语句类
    private void 遍历语句(抽象语法树监听器 监听器, 语句 语句) {
        监听器.进入语句(语句);
        if (语句 instanceof If语句 If语句) {
            遍历If语句(监听器, If语句);
        } else if (语句 instanceof While语句 While语句) {
            遍历While语句(监听器, While语句);
        } else if (语句 instanceof 函数调用语句 函数调用语句) {
            遍历函数调用语句(监听器, 函数调用语句);
        } else if (语句 instanceof 打印语句 打印语句) {
            遍历打印语句(监听器, 打印语句);
        } else if (语句 instanceof 赋值语句 赋值语句) {
            遍历赋值语句(监听器, 赋值语句);
        } else if (语句 instanceof 返回语句 返回语句) {
            遍历返回语句(监听器, 返回语句);
        }

        监听器.离开语句(语句);
    }

    private void 遍历If语句(抽象语法树监听器 监听器, If语句 If语句) {
        监听器.进入If语句(If语句);

        遍历(监听器, If语句.条件);
        遍历(监听器, If语句.真块);
        遍历(监听器, If语句.假块);

        监听器.离开If语句(If语句);
    }

    private void 遍历While语句(抽象语法树监听器 监听器, While语句 While语句) {
        监听器.进入While语句(While语句);

        遍历(监听器, While语句.条件);
        遍历(监听器, While语句.代码块);

        监听器.离开While语句(While语句);
    }

    private void 遍历函数调用语句(抽象语法树监听器 监听器, 函数调用语句 函数调用语句) {
        监听器.进入函数调用语句(函数调用语句);

        for (var 参数 : 函数调用语句.参数) {
            遍历(监听器, 参数);
        }

        监听器.离开函数调用语句(函数调用语句);
    }

    private void 遍历打印语句(抽象语法树监听器 监听器, 打印语句 打印语句) {
        监听器.进入打印语句(打印语句);

        遍历(监听器, 打印语句.表达式);

        监听器.离开打印语句(打印语句);
    }

    private void 遍历赋值语句(抽象语法树监听器 监听器, 赋值语句 赋值语句) {
        监听器.进入赋值语句(赋值语句);

        遍历(监听器, 赋值语句.左值);
        遍历(监听器, 赋值语句.右值);

        监听器.离开赋值语句(赋值语句);
    }

    private void 遍历返回语句(抽象语法树监听器 监听器, 返回语句 返回语句) {
        监听器.进入返回语句(返回语句);

        遍历(监听器, 返回语句.返回值);

        监听器.离开返回语句(返回语句);
    }

    // endregion


    // region 表达式类
    
    private void 遍历表达式(抽象语法树监听器 监听器, 表达式 表达式) {
        监听器.进入表达式(表达式);
        if (表达式 instanceof 实例化表达式 实例化表达式) {
            遍历实例化表达式(监听器, 实例化表达式);
        } else if (表达式 instanceof 成员访问表达式 成员访问表达式) {
            遍历成员访问表达式(监听器, 成员访问表达式);
        } else if (表达式 instanceof 二元表达式 二元表达式) {
            遍历二元表达式(监听器, 二元表达式);
        }

        监听器.离开表达式(表达式);
    }
    
    private void 遍历实例化表达式(抽象语法树监听器 监听器, 实例化表达式 实例化表达式) {
        监听器.进入实例化表达式(实例化表达式);
        监听器.离开实例化表达式(实例化表达式);
    }

    private void 遍历成员访问表达式(抽象语法树监听器 监听器, 成员访问表达式 成员访问表达式) {
        监听器.进入成员访问表达式(成员访问表达式);

        遍历(监听器, 成员访问表达式.对象);
        遍历(监听器, 成员访问表达式.成员);

        监听器.离开成员访问表达式(成员访问表达式);
    }
    
    // endregion

    
    // region 表达式类.二元表达式类
    private void 遍历二元表达式(抽象语法树监听器 监听器, 二元表达式 二元表达式) {
        监听器.进入二元表达式(二元表达式);

        if (二元表达式 instanceof 加法表达式 加法表达式) {
            遍历加法表达式(监听器, 加法表达式);
        } else if (二元表达式 instanceof 减法表达式 减法表达式) {
            遍历减法表达式(监听器, 减法表达式);
        } else if (二元表达式 instanceof 判等表达式 判等表达式) {
            遍历判等表达式(监听器, 判等表达式);
        } else if (二元表达式 instanceof 小于表达式 小于表达式) {
            遍历小于表达式(监听器, 小于表达式);
        } else if (二元表达式 instanceof 乘法表达式 乘法表达式) {
            遍历乘法表达式(监听器, 乘法表达式);
        }

        监听器.离开二元表达式(二元表达式);
    }

    private void 遍历乘法表达式(抽象语法树监听器 监听器, 乘法表达式 乘法表达式) {
        监听器.进入乘法表达式(乘法表达式);

        遍历(监听器, 乘法表达式.左值);
        遍历(监听器, 乘法表达式.右值);

        监听器.离开乘法表达式(乘法表达式);
    }

    private void 遍历减法表达式(抽象语法树监听器 监听器, 减法表达式 减法表达式) {
        监听器.进入减法表达式(减法表达式);

        遍历(监听器, 减法表达式.左值);
        遍历(监听器, 减法表达式.右值);

        监听器.离开减法表达式(减法表达式);
    }

    private void 遍历判等表达式(抽象语法树监听器 监听器, 判等表达式 判等表达式) {
        监听器.进入判等表达式(判等表达式);

        遍历(监听器, 判等表达式.左值);
        遍历(监听器, 判等表达式.右值);

        监听器.离开判等表达式(判等表达式);
    }

    private void 遍历加法表达式(抽象语法树监听器 监听器, 加法表达式 加法表达式) {
        监听器.进入加法表达式(加法表达式);

        遍历(监听器, 加法表达式.左值);
        遍历(监听器, 加法表达式.右值);

        监听器.离开加法表达式(加法表达式);
    }

    private void 遍历小于表达式(抽象语法树监听器 监听器, 小于表达式 小于表达式) {
        监听器.进入小于表达式(小于表达式);

        遍历(监听器, 小于表达式.左值);
        遍历(监听器, 小于表达式.右值);

        监听器.离开小于表达式(小于表达式);
    }

    // endregion


    // region 字面量类

    private void 遍历字面量(抽象语法树监听器 监听器, 字面量 字面量) {
        监听器.进入字面量(字面量);
        if (字面量 instanceof 整数型字面量 整数型字面量) {
            遍历整数型字面量(监听器, 整数型字面量);
        } else if (字面量 instanceof 文本型字面量 文本型字面量) {
            遍历文本型字面量(监听器, 文本型字面量);
        } else if (字面量 instanceof 浮点型字面量 浮点型字面量) {
            遍历浮点型字面量(监听器, 浮点型字面量);
        } else if (字面量 instanceof 字符型字面量 字符型字面量) {
            遍历字符型字面量(监听器, 字符型字面量);
        }

        监听器.离开字面量(字面量);
    }

    private void 遍历字符型字面量(抽象语法树监听器 监听器, 字符型字面量 字符型字面量) {
        监听器.进入字符型字面量(字符型字面量);
        监听器.离开字符型字面量(字符型字面量);
    }

    private void 遍历整数型字面量(抽象语法树监听器 监听器, 整数型字面量 整数型字面量) {
        监听器.进入整数型字面量(整数型字面量);
        监听器.离开整数型字面量(整数型字面量);
    }

    private void 遍历文本型字面量(抽象语法树监听器 监听器, 文本型字面量 文本型字面量) {
        监听器.进入文本型字面量(文本型字面量);
        监听器.离开文本型字面量(文本型字面量);
    }

    private void 遍历浮点型字面量(抽象语法树监听器 监听器, 浮点型字面量 浮点型字面量) {
        监听器.进入浮点型字面量(浮点型字面量);
        监听器.离开浮点型字面量(浮点型字面量);
    }

    // endregion
}
